#include "../input.h"
#include "../window.h"

NX_Error WM_InputKeyboardInit(void)
{
    g_wm_input.kbd_solt = NX_DeviceOpen("keyboard0", 0);
    if (g_wm_input.kbd_solt == NX_SOLT_INVALID_VALUE)
    {
        return NX_EPERM;
    }
    g_wm_input.key_modify = 0;
    g_wm_input.led_state = 0;
    NX_DeviceControl(g_wm_input.kbd_solt, NX_INPUT_EVENT_CMD_GETLED, &g_wm_input.led_state);
    return NX_EOK;
}

NX_Error WM_InputKeyboardExit(void)
{
    NX_DeviceClose(g_wm_input.kbd_solt);
    return NX_EOK;
}

NX_Error WM_InputJoystickInit(void)
{
    g_wm_input.joystick_solt = NX_DeviceOpen("joystick0", 0);
    if (g_wm_input.joystick_solt == NX_SOLT_INVALID_VALUE)
    {
        return NX_EPERM;
    }
    return NX_EOK;
}

NX_Error WM_InputJoystickExit(void)
{
    NX_DeviceClose(g_wm_input.joystick_solt);
    return NX_EOK;
}

NX_Error WM_InputMouseInit(void)
{
    NX_Error err;

    g_wm_input.mouse_solt = NX_DeviceOpen("mouse0", 0);
    if (g_wm_input.kbd_solt == NX_SOLT_INVALID_VALUE)
    {
        return err;
    }
    g_wm_input.mouse_x = 0;
    g_wm_input.mouse_y = 0;
    g_wm_input.prev_mouse_x = 0;
    g_wm_input.prev_mouse_y = 0;
    return NX_EOK;
}

NX_Error WM_InputMouseExit(void)
{
    NX_DeviceClose(g_wm_input.mouse_solt);
    return NX_EOK;
}

NX_PRIVATE NX_Error ReadKeyboard(NX_InputEvent * event)
{
    if (NX_DeviceRead(g_wm_input.kbd_solt, event, 0, sizeof(NX_InputEvent)) <= 0)
    {
        return NX_ENORES;
    }

    /* handle event */
    if (event->type != NX_EV_KEY)
    {
        return NX_EPERM;
    }

    if (event->value == 1)
    {
        WM_KeyboardDown(event->code);
    }
    else
    {
        WM_KeyboardUp(event->code);
    }
    return NX_EOK;
}

NX_PRIVATE NX_Error ReadMouse(NX_InputEvent * event)
{
    int x_rel = 0;
    int y_rel = 0;
    int z_rel = 0;
    int mouse_x_rel = 0;
    int mouse_y_rel = 0;
    int flag_rel = 0;

need_next:
    if (NX_DeviceRead(g_wm_input.mouse_solt, event, 0, sizeof(NX_InputEvent)) <= 0)
    {
        return NX_ENORES;
    }
    switch (event->type) {
    case NX_EV_REL:
        if ((event->code) == NX_REL_X) {
            x_rel += event->value; 
            flag_rel  = 1;
            goto  need_next;
        } else if ((event->code) == NX_REL_Y) {
            y_rel    += event->value; 
            flag_rel  = 1;
            goto  need_next;
        } else if ( (event->code) == NX_REL_WHEEL ) {
            z_rel = (int )event->value;
            WM_MouseWheel(z_rel);
            return NX_EOK;
        } else {
            return NX_EOK;
        }
        break;
    case NX_EV_KEY:
        if ((event->code) == NX_BTN_MOUSE_LEFT){
            if (event->value > 0) {
                WM_MouseButtonDown(NX_BTN_MOUSE_LEFT);
            } else {
                WM_MouseButtonUp(NX_BTN_MOUSE_LEFT);
            }
            return NX_EOK;
        } else if ((event->code) == NX_BTN_MOUSE_MIDDLE) {
            if (event->value > 0) {
                WM_MouseButtonDown(NX_BTN_MOUSE_MIDDLE);
            } else {
                WM_MouseButtonUp(NX_BTN_MOUSE_MIDDLE);
            }
            return NX_EOK;
        } else if ((event->code) == NX_BTN_MOUSE_RIGHT) {
            if (event->value > 0) {
                WM_MouseButtonDown(NX_BTN_MOUSE_RIGHT);
            } else {
                WM_MouseButtonUp(NX_BTN_MOUSE_RIGHT);
            }
            return NX_EOK;
        } else {
            return NX_EOK;
        }
        break;
    case NX_EV_MISC:
        return NX_EOK;
    case NX_EV_SYNC:
        mouse_x_rel += (int)x_rel;
        mouse_y_rel += (int)y_rel;

        x_rel = 0;
        y_rel = 0;
        if (flag_rel == 1) {
            WM_MouseMotion(mouse_x_rel, mouse_y_rel);
            flag_rel = 0;
            return NX_EOK;
        }
        flag_rel = 0;
        break;
    default:
        break;
    }
    return NX_ENORES;
}

NX_PRIVATE NX_Error ReadJoystick(NX_InputEvent * event)
{
    if (NX_DeviceRead(g_wm_input.joystick_solt, event, 0, sizeof(NX_InputEvent)) <= 0)
    {
        return NX_ENORES;
    }

    /* handle event */
    if (event->type != NX_EV_KEY)
    {
        return NX_EPERM;
    }

    if (event->value == 1)
    {
        WM_SendKeycode(NX_KEYDOWN_EVENT, event->code);
    }
    else
    {
        WM_SendKeycode(NX_KEYUP_EVENT, event->code);
    }
    return NX_EOK;
}

NX_Error WM_InputRead(NX_Solt solt)
{
    NX_InputEvent event;
    NX_MemZero(&event, sizeof(NX_InputEvent));
    if (solt == g_wm_input.kbd_solt)
    {
        return ReadKeyboard(&event);
    }
    if (solt == g_wm_input.mouse_solt)
    {
        return ReadMouse(&event);
    }
    if (solt == g_wm_input.joystick_solt)
    {
        return ReadJoystick(&event);
    }
    return NX_ENORES;
}
